package com.bifrost.service.impl;

import com.bifrost.entity.MessageRecord;
import com.bifrost.common.model.ResultModel;
import com.bifrost.repository.MessageRecordRepository;
import com.bifrost.service.CustomerService;
import com.bifrost.service.SmsService;
import com.bifrost.util.HttpClientUtil;
import org.apache.commons.lang.StringUtils;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author rangjf
 * @date 2017/10/19
 */
@Service
public class SmsServiceImpl implements SmsService {

    @Autowired
    RedisTemplate<String, String> redis;
    @Autowired
    CustomerService customerService;
    @Autowired
    MessageRecordRepository messageRecordRepository;

    private static final Logger logger = LoggerFactory.getLogger(SmsServiceImpl.class);

    @Value("${sms.api.url:#{null}}")
    private String smsApiUrl;
    @Value("${sms.api.smsId:#{null}}")
    private String smsId;
    @Value("${sms.api.smsPassword:#{null}}")
    private String smsPassword;
    @Value("${phone.max.limit:#{10}}")
    private int maxLimit;
    @Value("${phone.req.limit:#{1}}")
    private int reqLimit;

    @Override
    public ResultModel sendMessage(String phone) {
        //限制1分钟之内只能发送一次短信
        String hasLimit = redis.boundValueOps("requested:" + phone).get();
        if (hasLimit != null) {
            return ResultModel.ok()
                    .put("flag", false)
                    .put("msg", "操作过于频繁,请稍后再试");
        }
        //限制每天发送验证码最大次数
        String count = redis.boundValueOps("maxCount:" + phone).get();
        if (count == null) {
            count = "1";
            redis.boundValueOps("maxCount:" + phone).set("1", 1, TimeUnit.DAYS);
        }
        if (maxLimit < (Integer.valueOf(count))) {
            return ResultModel.ok()
                    .put("flag", false)
                    .put("msg", "操作过于频繁,请明天再试");
        }
        redis.boundValueOps("maxCount:" + phone).increment(1);
        //发送验证码
        String code = String.valueOf((int) ((Math.random() * 9 + 1) * 100000));
        //验证码：10分钟之内有效
        redis.boundValueOps("validateCode:" + phone).set(code, 10, TimeUnit.MINUTES);
        //判断标志，1分钟之内不能发第二条短信
        redis.boundValueOps("requested:" + phone).set(code, 1, TimeUnit.MINUTES);
        String counts = buildRequestAndExecute(phone, "您的验证码是" + code + "请在10分钟内完成验证。");
        if (StringUtils.isNotEmpty(counts)) {
            return ResultModel.ok()
                    .put("flag", true)
                    .put("msg", "成功");
        } else {
            return ResultModel.error()
                    .put("flag", false)
                    .put("msg", "发送失败");
        }
    }

    @Override
    public Boolean checkMessage(String phone, String msg) {
        String code = redis.boundValueOps("validateCode:" + phone).get();
        if (code == null) {
            return Boolean.FALSE;
        }
        if (msg.equals(code)) {
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }

    /**
     * 发送客户短信
     *
     * @param phone
     * @param msg
     * @return
     */
    @Override
    public String sendCustomerMessage(String phone, String msg) {
        return buildRequestAndExecute(phone, msg);
    }

    private Map buildRequest(String phone, String msg) {
        Map<String, String> param = new HashMap<String, String>(6);
        param.put("userId", smsId);
        param.put("password", smsPassword);
        param.put("pszMobis", phone);
        param.put("pszMsg", msg);
        param.put("iMobiCount", "1");
        param.put("pszSubPort", "*");
        param.put("MsgId", String.valueOf((int) (Math.random() * 100)));
        return param;
    }

    private String buildRequestAndExecute(String phone, String msg) {
        Map request = buildRequest(phone, msg);
        return execute(request);
    }

    private String execute(Map request) {
        if (StringUtils.isNotBlank(smsApiUrl)) {
            String xmlResult = HttpClientUtil.doGet(smsApiUrl, request);
            if (StringUtils.isNotEmpty(xmlResult)) {
                String result = getResult(xmlResult);
                //仅记录成功记录
                if (StringUtils.isNotEmpty(result) && result.length() > 10) {
                    return countTimes().toString();
                } else if (StringUtils.isEmpty(result)) {
                    logger.error("短信发送失败：提交失败");
                } else {
                    logger.error("短信发送失败，错误码：" + result);
                }
            }
            logger.error("请求短信接口失败");
        }
        return null;
    }

    private String getResult(String xmlString) {
        try {
            Document document = DocumentHelper.parseText(xmlString);
            Element element = document.getRootElement();
            return element.getText();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 统计成功发送短信次数
     *
     * @return
     */
    @Override
    public Long countTimes() {
        List<MessageRecord> list = messageRecordRepository.findAll();
        if (list == null || list.isEmpty()) {
            MessageRecord messageRecord = new MessageRecord();
            messageRecord.setCount(1L);
            MessageRecord dbMessageRecord = messageRecordRepository.save(messageRecord);
            return dbMessageRecord.getCount();
        }
        MessageRecord before = list.get(0);
        before.setCount(before.getCount() + 1);
        MessageRecord after = messageRecordRepository.save(before);
        return after.getCount();
    }
}
